package com.mm.cloud.sys.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mm.cloud.common.core.constant.CommonConstants;
import com.mm.cloud.common.core.enums.DeleteEnum;
import com.mm.cloud.common.core.exception.BaseException;
import com.mm.cloud.common.core.result.Result;
import com.mm.cloud.common.core.result.ResultConstants;
import com.mm.cloud.common.core.result.ResultUtil;
import com.mm.cloud.common.security.annotation.ParameterCheck;
import com.mm.cloud.common.security.loginuser.LoginUser;
import com.mm.cloud.common.security.helper.LoginUserHelper;
import com.mm.cloud.feign.sys.api.vo.LoginUserVO;
import com.mm.cloud.sys.dto.form.UserDTO;
import com.mm.cloud.sys.dto.form.UserToRoleDTO;
import com.mm.cloud.sys.dto.query.QueryUserDTO;
import com.mm.cloud.sys.entity.User;
import com.mm.cloud.sys.mapper.UserMapper;
import com.mm.cloud.sys.service.IUserService;
import com.mm.cloud.sys.vo.UserVO;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户基础信息 服务实现类
 * </p>
 *
 * @author mr
 * @since 2020-09-15
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Override
    public Result<List<UserVO>> getUserList(QueryUserDTO dto) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        dto.setCompanyId(loginUser.getCompanyId());
        IPage<UserVO> page = this.baseMapper.getUserList(new Page<>(dto.getPage(), dto.getLimit()), dto);
        return ResultUtil.success(page.getRecords(), page.getTotal());
    }

    @Override
    @ParameterCheck
    public Result<String> saveUser(UserDTO dto) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        // 校验手机号是否存
        User existUser = this.getOne(Wrappers.<User>lambdaQuery().eq(User::getPhone, dto.getPhone()).eq(User::getIsDelete, DeleteEnum.NOT_DELETE.getStatus()));
        if (Objects.nonNull(existUser)) {
            return ResultUtil.fail("手机号已被使用");
        }
        // 校验用户名是否存
        existUser = this.getOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, dto.getUsername()).eq(User::getIsDelete, DeleteEnum.NOT_DELETE.getStatus()));
        if (Objects.nonNull(existUser)) {
            return ResultUtil.fail("用户名已被使用");
        }
        User user = new User();
        BeanUtils.copyProperties(dto, user);
        user.setPassword(LoginUserHelper.encryptPassword(CommonConstants.PASSWORD));
        user.setCompanyId(loginUser.getCompanyId());
        user.setCreaterId(loginUser.getUserId());
        user.setCreateTime(LocalDateTime.now());
        user.setIsDelete(DeleteEnum.NOT_DELETE.getStatus());
        this.save(user);
        return ResultUtil.success();
    }

    @Override
    @ParameterCheck
    public Result<String> updateUser(UserDTO dto) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        User user = this.getUserAssert(loginUser.getCompanyId(), dto.getId());
        // 校验手机号是否存
        User existUser = this.getOne(Wrappers.<User>lambdaQuery()
                .eq(User::getPhone, dto.getPhone())
                .eq(User::getIsDelete, DeleteEnum.NOT_DELETE.getStatus())
                .ne(User::getId, user.getId()));
        if (Objects.nonNull(existUser)) {
            return ResultUtil.fail("手机号已被使用");
        }
        // 校验用户名是否存
        existUser = this.getOne(Wrappers.<User>lambdaQuery()
                .eq(User::getUsername, dto.getUsername())
                .eq(User::getIsDelete, DeleteEnum.NOT_DELETE.getStatus())
                .ne(User::getId, user.getId()));
        if (Objects.nonNull(existUser)) {
            return ResultUtil.fail("用户名已被使用");
        }
        BeanUtils.copyProperties(dto, user);
        user.setUpdaterId(loginUser.getUserId());
        user.setUpdateTime(LocalDateTime.now());
        this.updateById(user);
        return ResultUtil.success();
    }

    @Override
    @ParameterCheck
    public Result<String> deleteUser(@NotNull(message = "参数不能为空") Long userId) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        User user = this.getUserAssert(loginUser.getCompanyId(), userId);
        user.setUpdaterId(loginUser.getUserId());
        user.setUpdateTime(LocalDateTime.now());
        user.setIsDelete(DeleteEnum.DELETE.getStatus());
        this.updateById(user);
        return ResultUtil.success();
    }

    @Override
    @ParameterCheck
    public Result<List<Long>> getRoleByUserId(@NotNull(message = "参数不能为空") Long userId) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        return ResultUtil.success(this.baseMapper.getRoleByUserId(loginUser.getCompanyId(), userId));
    }

    @Override
    @ParameterCheck
    @Transactional
    public Result<String> setUserToRole(UserToRoleDTO dto) {
        LoginUser loginUser = LoginUserHelper.getLoginUser();
        this.baseMapper.deleteUserToRole(loginUser.getCompanyId(), dto.getUserId());
        if (StringUtils.isNotEmpty(dto.getRoleIds())) {
            this.baseMapper.setUserToRole(loginUser.getCompanyId(), dto.getUserId(), Arrays.stream(dto.getRoleIds().split(",")).map(Long::parseLong).collect(Collectors.toList()));
        }
        return ResultUtil.success();
    }

    @Override
    @ParameterCheck
    public Result<LoginUserVO> getUserByUsername(@NotBlank(message = "用户名不能为空") String username) {
        User user = this.baseMapper.selectOne(Wrappers.<User>query().lambda().eq(User::getUsername, username).eq(User::getIsDelete, DeleteEnum.NOT_DELETE.getStatus()));
        return this.buildLoginUser(user);
    }

    @Override
    @ParameterCheck
    public Result<LoginUserVO> getUserByPhone(@NotBlank(message = "手机号不能为空") String phone) {
        User user = this.baseMapper.selectOne(Wrappers.<User>query().lambda().eq(User::getPhone, phone).eq(User::getIsDelete, DeleteEnum.NOT_DELETE.getStatus()));
        return this.buildLoginUser(user);
    }

    /**
     * 封装登录用户信息
     *
     * @param user 用户信息
     * @return 登录用户信息
     */
    private Result<LoginUserVO> buildLoginUser(User user) {
        if (user == null) {
            throw new BaseException("用户名或密码错误");
        }
        LoginUserVO loginUserVO = new LoginUserVO();
        BeanUtils.copyProperties(user, loginUserVO);
        Set<String> roles = new HashSet<>();
        if (CommonConstants.ADMIN.equals(user.getIsAdmin())) {
            roles.add(user.getIsAdmin());
        } else {
            List<String> roleList = this.baseMapper.getRoleCodeByUserId(user.getCompanyId(), user.getId());
            if (CollectionUtils.isNotEmpty(roleList)) {
                roles = new HashSet<>(roleList);
            }
        }
        loginUserVO.setRoles(roles);
        return ResultUtil.success(loginUserVO);
    }

    /**
     * 查询用户信息
     *
     * @param companyId 公司ID
     * @param userId    用户ID
     * @return User
     */
    private User getUserAssert(Long companyId, Long userId) {
        Assert.notNull(companyId, "companyId is null");
        Assert.notNull(userId, "userId is null");
        User user = this.getOne(Wrappers.<User>lambdaQuery().eq(User::getCompanyId, companyId).eq(User::getId, userId).eq(User::getIsDelete, DeleteEnum.NOT_DELETE.getStatus()));
        if (Objects.isNull(user)) {
            throw new BaseException(ResultConstants.QUERY_NOT_FOUND_DATA);
        }
        return user;
    }
}
